package microcredit;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

import microcredit.db.Backup;
import microcredit.model.ValidationException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class DatabaseUtilities {

	private static final Log LOGGER = LogFactory
			.getLog(DatabaseUtilities.class);


	public void backupDatabase() {
		File backupFolder = new File("./backup");
		backupFolder.mkdir();
	}

	public void runExport(File f) throws IOException, ValidationException {
		File currentDB = new File(MicroCredit.PATH_TO_DB);
		if (!currentDB.exists()) {
			throw new ValidationException("No database exists at location "
					+ MicroCredit.PATH_TO_DB);
		}
		if (!f.exists()) {
			f.createNewFile();
		}
		ZipOutputStream stream = new ZipOutputStream(new FileOutputStream(f));

		exportRecourse(currentDB, currentDB, stream);

		stream.flush();
		stream.close();
	}

	public void unzipFolder(File zipFile, File targetFolder) throws IOException {
		BufferedOutputStream dest = null;
		FileInputStream fis = new FileInputStream(zipFile);
		ZipInputStream zis = new ZipInputStream(new BufferedInputStream(fis));
		ZipEntry entry;
		while ((entry = zis.getNextEntry()) != null) {
			int count;
			byte data[] = new byte[2048];
			// write the files to the disk
			File out = new File(targetFolder, entry.getName());
			if (!out.getParentFile().exists())
				out.getParentFile().mkdirs();
			
			if (entry.isDirectory())
				out.mkdirs();
			else {
				FileOutputStream fos = new FileOutputStream(new File(targetFolder, entry.getName()));
				dest = new BufferedOutputStream(fos, 2048);
				while ((count = zis.read(data, 0, 2048)) != -1) {
					dest.write(data, 0, count);
				}				
				dest.flush();
				dest.close();
			}
		}
		zis.close();
	}
	
	
	public void zipFolder(File folder, File targetFile) throws IOException {
		ZipOutputStream stream = new ZipOutputStream(new FileOutputStream(targetFile));
		exportRecourse(folder, folder, stream);
		stream.flush();
		stream.close();
	}
	
	private void exportRecourse(File rootFolder, File f, ZipOutputStream stream)
			throws IOException, ValidationException {
		if (f.isDirectory()) {
			File[] children = f.listFiles();
			for (File file : children) {
				exportRecourse(rootFolder, file, stream);
			}
			return;
		}

		String currentPath = f.getAbsolutePath();
		String rootPath = rootFolder.getAbsolutePath();
		if (currentPath.indexOf(rootPath) == -1) {
			throw new ValidationException("Something strange happened");
		}
		int cutIndex = currentPath.indexOf(rootPath);

		String relativeFileName = currentPath.substring(cutIndex
				+ rootPath.length() + 1, currentPath.length());

		stream.putNextEntry(new ZipEntry(relativeFileName));

		FileInputStream input = new FileInputStream(f);
		byte[] buffer = new byte[1024];
		int read = -1;
		while ((read = input.read(buffer)) != -1) {
			stream.write(buffer, 0, read);

		}
		input.close();
		stream.closeEntry();
	}

	private static DatabaseUtilities instance;

	public static DatabaseUtilities getInstance() {
		if (instance == null) {
			instance = new DatabaseUtilities();
		}
		return instance;
	}

}
